home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Experimental BBS Explossion 3
/
Experimental BBS Explossion III.iso
/
games
/
nhak_src.zip
/
SPELL.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-03-16
|
12KB
|
487 lines
/* SCCS Id: @(#)spell.c 3.0 88/09/18
*
* Copyright (c) M. Stephenson 1988
*/
/* NetHack may be freely redistributed. See license for details. */
#include "hack.h"
#ifdef SPELLS
static schar NEARDATA delay; /* moves left for this spell */
static struct obj NEARDATA *book; /* last/current book being xscribed */
#ifdef HARD
#define spelluses(spell) spl_book[spell-1].sp_uses
#define decrnuses(spell) spl_book[spell-1].sp_uses--
#endif /* HARD */
#define spellev(spell) spl_book[spell-1].sp_lev
#define spellname(spell) objects[spl_book[spell-1].sp_id].oc_name
#define spellid(spell) spl_book[spell-1].sp_id
static void FDECL(cursed_book, (int));
STATIC_PTR int NDECL(learn);
static int NDECL(getspell);
static char FDECL(spellet, (int));
static void
cursed_book(lev)
register int lev;
{
switch(rn2(lev)) {
case 0:
You("feel a wrenching sensation.");
tele(); /* teleport him */
break;
case 1:
You("feel threatened.");
aggravate();
break;
case 2:
make_blinded(Blinded + rn1(100,250),TRUE);
break;
case 3:
take_gold();
break;
case 4:
pline("These runes were just too much to comprehend.");
make_confused(HConfusion + rn1(7,16),FALSE);
break;
case 5:
pline("The book was coated with contact poison!");
if (uarmg) {
if (uarmg->rustfree)
Your("gloves seem unaffected.");
else if (uarmg->spe > -2) {
Your("gloves corrode!");
uarmg->spe--;
} else
Your("gloves %s quite corroded.",Blind ? "feel":"look");
break;
}
if(Poison_resistance) {
losestr(rn1(1,2));
losehp(rnd(6), "contact-poisoned spellbook", KILLED_BY_AN);
} else {
losestr(rn1(4,3));
losehp(rnd(10), "contact-poisoned spellbook", KILLED_BY_AN);
}
break;
case 6:
if(Antimagic) {
shieldeff(u.ux, u.uy);
pline("The book explodes, but you are unharmed!");
} else {
pline("As you read the book, it explodes in your %s!",
body_part(FACE));
losehp (2*rnd(10)+5, "exploding rune", KILLED_BY_AN);
}
break;
default:
rndcurse();
break;
}
return;
}
STATIC_PTR
int
learn()
{
register int i;
register unsigned booktype;
if (delay) { /* not if (delay++), so at end delay == 0 */
delay++;
return(1); /* still busy */
}
booktype = book->otyp;
for (i = 0; i < MAXSPELL; i++) {
if (spl_book[i].sp_id == booktype) {
#ifdef HARD
Your("knowledge of that spell is keener.");
spl_book[i].sp_uses += rn1(3,8-spl_book[i].sp_lev);
#else
pline("Oh, you already know that one!");
#endif
break;
} else if (spl_book[i].sp_id == NO_SPELL) {
spl_book[i].sp_id = booktype;
spl_book[i].sp_lev = objects[booktype].spl_lev;
spl_book[i].sp_flags = objects[booktype].bits;
#ifdef HARD
/* spells have 2 .. 10-level uses. */
/* ie 2 or 3 uses w/ most potent */
spl_book[i].sp_uses = rn1(3,8-spl_book[i].sp_lev);
#endif
You("add the spell to your repertoire.");
makeknown(booktype);
break;
}
}
if (i == MAXSPELL) impossible("Too many spells memorized!");
if (book->cursed) { /* maybe a demon cursed it */
cursed_book(objects[booktype].spl_lev);
}
useup(book);
book = 0;
return(0);
}
int
study_book(spellbook)
register struct obj *spellbook;
{
register int booktype = spellbook->otyp;
if (delay && spellbook == book)
You("continue your efforts to memorize the spell.");
else {
switch(booktype) {
/* level 1 spells */
case SPE_HEALING:
case SPE_DETECT_MONSTERS:
case SPE_FORCE_BOLT:
case SPE_LIGHT:
case SPE_SLEEP:
case SPE_KNOCK:
/* level 2 spells */
case SPE_MAGIC_MISSILE:
case SPE_CONFUSE_MONSTER:
case SPE_SLOW_MONSTER:
case SPE_CURE_BLINDNESS:
case SPE_CREATE_MONSTER:
case SPE_DETECT_FOOD:
case SPE_WIZARD_LOCK:
delay = -objects[booktype].oc_delay;
break;
/* level 3 spells */
case SPE_HASTE_SELF:
case SPE_CAUSE_FEAR:
case SPE_CURE_SICKNESS:
case SPE_DETECT_UNSEEN:
case SPE_EXTRA_HEALING:
case SPE_CHARM_MONSTER:
case SPE_CLAIRVOYANCE:
/* level 4 spells */
case SPE_LEVITATION:
case SPE_RESTORE_ABILITY:
case SPE_INVISIBILITY:
case SPE_FIREBALL:
case SPE_DETECT_TREASURE:
delay = -(objects[booktype].spl_lev - 1) * objects[booktype].oc_delay;
break;
/* level 5 spells */
case SPE_REMOVE_CURSE:
case SPE_MAGIC_MAPPING:
case SPE_CONE_OF_COLD:
case SPE_IDENTIFY:
case SPE_DIG:
/* level 6 spells */
case SPE_TURN_UNDEAD:
case SPE_POLYMORPH:
case SPE_CREATE_FAMILIAR:
case SPE_TELEPORT_AWAY:
delay = -objects[booktype].spl_lev * objects[booktype].oc_delay;
break;
/* level 7 spells */
case SPE_CANCELLATION:
case SPE_FINGER_OF_DEATH:
case SPE_GENOCIDE:
delay = -8 * objects[booktype].oc_delay;
break;
/* impossible */
default:
impossible("Unknown spellbook, %d;", booktype);
return(0);
}
if(!spellbook->blessed &&
(spellbook->cursed ||
rn2(20) > (ACURR(A_INT) + 4 + (int)(u.ulevel/2)
- 2*objects[booktype].spl_lev))) {
cursed_book(objects[booktype].spl_lev);
nomul(delay); /* study time */
delay = 0;
useup(spellbook);
return(1);
}
You("begin to memorize the runes.");
}
book = spellbook;
set_occupation(learn, "studying", 0);
return(1);
}
static int
getspell() {
register int maxs, ilet, i;
char lets[BUFSZ], buf[BUFSZ];
if (spl_book[0].sp_id == NO_SPELL) {
You("don't know any spells right now.");
return(0);
} else {
for(maxs = 1; (maxs < MAXSPELL) && (spl_book[maxs].sp_id != NO_SPELL); maxs++);
if (maxs >= MAXSPELL) {
impossible("Too many spells memorized.");
return(0);
}
for(i = 0; (i < maxs) && (i < 26); buf[++i] = 0) buf[i] = 'a' + i;
for(i = 26; (i < maxs) && (i < 52); buf[++i] = 0) buf[i] = 'A' + i - 26;
if (maxs == 1) Strcpy(lets, "a");
else if (maxs < 27) Sprintf(lets, "a-%c", 'a' + maxs - 1);
else if (maxs == 27) Sprintf(lets, "a-z A");
else Sprintf(lets, "a-z A-%c", 'A' + maxs - 27);
for(;;) {
pline("Cast which spell? [%s ?] ", lets);
if ((ilet = readchar()) == '?') {
(void) dovspell();
continue;
} else if ((ilet == '\033')||(ilet == '\n')||(ilet == ' '))
return(0);
else for(i = 0; buf[i] != 0; i++) if(ilet == buf[i]) return(++i);
You("don't know that spell.");
}
}
}
int
docast()
{
register int spell;
spell = getspell();
if (!spell) return(0);
return(spelleffects(spell,FALSE));
}
int
spelleffects(spell,atme)
register int spell;
boolean atme;
{
register int energy, damage;
#ifdef HARD
boolean confused = (Confusion != 0);
#endif
struct obj *pseudo;
#ifdef HARD
/* note that trying to cast it decrements the # of uses, */
/* even if the mage does not have enough food/energy to use */
/* the spell */
switch (spelluses(spell)) {
case 0:
pline ("That spell is too hard to recall at the moment.");
return(0);
case 1:
pline ("You can barely remember the runes of this spell.");
break;
case 2:
pline ("This spell is starting to be over-used.");
break;
default:
break;
}
decrnuses(spell);
#endif
energy = spellev(spell);
if (u.uhave_amulet) {
You("feel the amulet draining your energy away.");
energy *= rnd(6);
}
if(energy > u.uen) {
You("don't have enough energy to cast that spell.");
return(0);
} else if ((u.uhunger <= 100 && spell != SPE_DETECT_FOOD) ||
(ACURR(A_STR) < 6)) {
You("lack the strength for that spell.");
return(0);
} else {
if (spell != SPE_DETECT_FOOD)
morehungry(energy * 10);
u.uen -= energy;
}
flags.botl = 1;
#ifdef HARD
if (confused ||
((int)(ACURR(A_INT) + Luck) - 3 * spellev(spell)) < 0) {
if (Hallucination)
pline("Far out... a light show!");
else pline("The air around you crackles as you goof up.");
return(0);
}
#endif
/* pseudo is a temporary "false" object containing the spell stats. */
pseudo = mksobj(spellid(spell),FALSE);
pseudo->blessed = pseudo->cursed = 0;
pseudo->quan = 20; /* do not let useup get it */
switch(pseudo->otyp) {
/* These spells are all duplicates of wand effects */
case SPE_FORCE_BOLT:
case SPE_SLEEP:
case SPE_MAGIC_MISSILE:
case SPE_KNOCK:
case SPE_SLOW_MONSTER:
case SPE_WIZARD_LOCK:
case SPE_FIREBALL:
case SPE_CONE_OF_COLD:
case SPE_DIG:
case SPE_TURN_UNDEAD:
case SPE_POLYMORPH:
case SPE_TELEPORT_AWAY:
case SPE_CANCELLATION:
case SPE_FINGER_OF_DEATH:
case SPE_LIGHT:
case SPE_DETECT_UNSEEN:
#ifdef MACOS
if (pseudo->otyp == SPE_DIG)
{
segments |= SEG_SPELL;
}
#endif
if (!(objects[pseudo->otyp].bits & NODIR)) {
if (atme) u.dx = u.dy = u.dz = 0;
else (void) getdir(1);
if(!u.dx && !u.dy && !u.dz) {
if((damage = zapyourself(pseudo)))
losehp(damage,
self_pronoun("zapped %sself with a spell", "him"),
NO_KILLER_PREFIX);
} else weffects(pseudo);
} else weffects(pseudo);
break;
/* These are all duplicates of scroll effects */
case SPE_CONFUSE_MONSTER:
case SPE_DETECT_FOOD:
case SPE_CAUSE_FEAR:
case SPE_CHARM_MONSTER:
case SPE_REMOVE_CURSE:
case SPE_MAGIC_MAPPING:
case SPE_CREATE_MONSTER:
case SPE_IDENTIFY:
case SPE_GENOCIDE:
(void) seffects(pseudo);
break;
case SPE_HASTE_SELF:
case SPE_DETECT_TREASURE:
case SPE_DETECT_MONSTERS:
case SPE_LEVITATION:
case SPE_RESTORE_ABILITY:
case SPE_INVISIBILITY:
(void) peffects(pseudo);
break;
case SPE_HEALING:
You("feel a bit better.");
healup(rnd(8), 0, 0, 0);
break;
case SPE_CURE_BLINDNESS:
healup(0, 0, 0, 1);
break;
case SPE_CURE_SICKNESS:
if (Sick) You("are no longer ill.");
healup(0, 0, 1, 0);
break;
case SPE_EXTRA_HEALING:
You("feel a fair bit better.");
healup(d(2,8), 1, 0, 0);
break;
case SPE_CREATE_FAMILIAR:
make_familiar((struct obj *)0);
break;
case SPE_CLAIRVOYANCE:
do_vicinity_map();
break;
default:
impossible("Unknown spell %d attempted.", spell);
obfree(pseudo, (struct obj *)0);
return(0);
}
obfree(pseudo, (struct obj *)0); /* now, get rid of it */
return(1);
}
void
losespells() {
register boolean confused = (Confusion != 0);
register int n, nzap, i;
book = 0;
for(n = 0;(spl_book[n].sp_id != NO_SPELL) && (n < MAXSPELL); n++);
if (!n) return;
if (n < MAXSPELL) {
nzap = rnd(n);
if (nzap < n) nzap += confused;
for (i = 0; i < nzap; i++) spl_book[n-i-1].sp_id = NO_SPELL;
} else impossible("Too many spells memorized!");
return;
}
static char
spellet(spl)
int spl;
{
return (spl < 27) ? ('a' + spl - 1) : ('A' + spl - 27);
}
int
dovspell() {
register int maxs, i;
char buf[BUFSZ], any[BUFSZ];
if (spl_book[0].sp_id == NO_SPELL) {
You("don't know any spells right now.");
return 0;
}
for(maxs = 1; (maxs < MAXSPELL) && (spl_book[maxs].sp_id != NO_SPELL); maxs++);
if (maxs >= MAXSPELL) {
impossible("Too many spells memorized.");
return 0;
}
morc = 0; /* just to be sure */
cornline(0, "Currently known spells:");
for(i = 1; i <= maxs; i++) {
#ifdef HARD
Sprintf(buf, "%c %c %s (%d)",
spellet(i), (spelluses(i)) ? '-' : '*',
spellname(i), spellev(i));
#else
Sprintf(buf, "%c %s (%d)",
spellet(i),
spellname(i), spellev(i));
#endif
cornline(1, buf);
any[i-1] = spellet(i);
}
any[i-1] = 0;
cornline(2, any);
return 0;
}
#endif /* SPELLS /**/